package com.dt.common.utils.http;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


/**
 * 使用okhttp3的工具类
 *
 * @author yangxuegang
 * @date 2022/02/16 18:05
 */
public class HttpUtilTool {
	private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
	private static final String JSON_TYPE = "application/json; charset=utf-8";
	private static final MediaType JSON = MediaType.parse(JSON_TYPE);
	private static final String HTTPS_PREFIX = "https";

	/**
	 * 发送HTTP post请求
	 *
	 * @param url     url链接
	 * @param strBody body内容
	 * @return 返回结果
	 */
	public String sendPost(String url, Headers headers, String strBody) {

		try {

			boolean userSsl = false;
			if (StringUtils.startsWith(url, HTTPS_PREFIX)) {
				userSsl = true;
			}

			OkHttpClient client = buildClient(userSsl);
			RequestBody body = RequestBody.create(JSON, strBody);
			if (Objects.isNull(headers)) {
				Headers.Builder hb = new Headers.Builder();
				headers = hb.build();
			}
			Request request = new Request.Builder().url(url)
				.headers(headers)
				.addHeader("Content-Type", JSON_TYPE)
				.addHeader("Accept", JSON_TYPE)
				.post(body).build();
			Response response = client.newCall(request).execute();
			String responseBody = Objects.requireNonNull(response.body()).string();


			int successCode = 200;
			if (response.code() == successCode) {
				return responseBody;
			} else {
				return String.format("post error!!code is [%d],message is [%s],body is [%s]",
					response.code(),
					response.message(), responseBody);
			}
		} catch (Exception e) {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("message", e.getMessage());

			return jsonObject.toJSONString();
		}
	}

	/**
	 * 发送HTTP get
	 *
	 * @param url url链接
	 * @return 返回结果
	 */
	public String sendGet(String url, Headers headers) throws IOException {
		boolean userSsl = false;
		if (StringUtils.startsWith(url, HTTPS_PREFIX)) {
			userSsl = true;
		}
		OkHttpClient client = buildClient(userSsl);
		if (Objects.isNull(headers)) {
			Headers.Builder hb = new Headers.Builder();
			headers = hb.build();
		}
		HttpUrl.Builder urlBuild = HttpUrl.parse(url).newBuilder();
		Request request = new Request.Builder().url(urlBuild.build())
			.headers(headers)
			.addHeader("Content-Type", JSON_TYPE)
			.addHeader("Accept", JSON_TYPE)
			.get().build();
		Response response = client.newCall(request).execute();
		return response.body().string();
	}

	private OkHttpClient buildClient(boolean enableSsl) {
		OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(30,
			TimeUnit.SECONDS).readTimeout(300, TimeUnit.SECONDS).retryOnConnectionFailure(true);
		try {
			if (Boolean.TRUE.equals(enableSsl)) {
				X509TrustManager trustManager = new TrustManagerCustomer();
				builder.sslSocketFactory(SslSocketClient.getSslSocketFactory(), trustManager);
				builder.hostnameVerifier((hostname, session) -> true);
			}
		} catch (NoSuchAlgorithmException e) {
			log.error("buildClient", e);
		} catch (KeyManagementException e) {
			log.error("buildClient", e);
		}
		return builder.build();
	}


	static class TrustManagerCustomer implements TrustManager, X509TrustManager {

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[0];
		}

		@Override
		public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
			// don't check
		}

		@Override
		public void checkClientTrusted(X509Certificate[] certs, String authType) {
			// don't check
		}
	}

	static class SslSocketClient {
		// 获取这个SSLSocketFactory
		static SSLSocketFactory getSslSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
			SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
			sslContext.init(null, getTrustManager(),
				new SecureRandom());
			return sslContext.getSocketFactory();
		}

		private static final String KEY_STORE_TYPE_JKS = "JKS";

		public static KeyManager[] getKeyManagers(InputStream bks, String keystorePass) {
			KeyStore clientKeyStore = null;
			try {
				clientKeyStore = KeyStore.getInstance(KEY_STORE_TYPE_JKS);
				clientKeyStore.load(bks, keystorePass.toCharArray());
				bks.close();
				KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
				keyManagerFactory.init(clientKeyStore, keystorePass.toCharArray());
				KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
				return keyManagers;
			} catch (KeyStoreException | UnrecoverableKeyException | CertificateException e) {
				e.printStackTrace();
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return new KeyManager[] {};
		}

		// 获取TrustManager
		private static TrustManager[] getTrustManager() {
			return new TrustManager[] {
				new TrustManagerCustomer()
			};
		}
	}

}
